#ifndef SDK_OHOS_API_OHOS_PEER_CONNECTION_INTERFACE_H_
#define SDK_OHOS_API_OHOS_PEER_CONNECTION_INTERFACE_H_

#include <memory>
#include "api/ref_count.h"
#include "api/scoped_refptr.h"
#include "api/peer_connection_interface.h"
#include "api/media_types.h"
#include "api/rtp_parameters.h"
#include "api/rtp_transceiver_interface.h"
#include "ohos_media_stream_interface.h"
#include "ohos_media_track_interface.h"
#include "ohos_audio_track_interface.h"
#include "ohos_video_track_interface.h"
#include "ohos_rtp_sender_interface.h"
#include "ohos_rtp_receiver_interface.h"
#include "ohos_media_constraints_interface.h"
#include "ohos_rtp_sender_interface.h"
#include "ohos_rtp_receiver_interface.h"
#include "ohos_rtp_transceiver_interface.h"
#include "ohos_rtp_transceiver_init_interface.h"
#include "api/stats/rtc_stats_report.h"
#include "ohos_data_channel_interface.h"

namespace ohoswebrtc {

using CreateSessionDescriptionSuccess = std::function<void(webrtc::SessionDescriptionInterface*)>;
using CreateSessionDescriptionFailure = std::function<void(webrtc::RTCError)>;
using OnSdpDescriptionCallback = std::function<void(webrtc::RTCError)>;
using OnStatsCollectorCompletion =  std::function<void(const rtc::scoped_refptr<const webrtc::RTCStatsReport> &report)>;

class OHOSPeerConnectionObserver {

  public:
    /** Triggered when the SignalingState changed */
    virtual void OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState new_state) = 0;
    /** Triggered when media is received on a new stream from remote peer */
    virtual void OnAddStream(rtc::scoped_refptr<OHOSMediaStreamInterface> stream) {}
    /** Triggered when a remote peer closes a stream */
    virtual void OnRemoveStream(rtc::scoped_refptr<OHOSMediaStreamInterface> stream) {}
    /** Triggered when a remote peer opens a data channel. */
    virtual void OnDataChannel(rtc::scoped_refptr<OHOSDataChannelInterface> data_channel) = 0; 
    /** Triggered when renegotiation is needed. For example, an ICE restart has begun */
    virtual void OnRenegotiationNeeded() {}
    /** Called any time the legacy IceConnectionState changes. */
    virtual void OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state) {}
    /** Called any time the standards-compliant IceConnectionState changes */
    virtual void OnStandardizedIceConnectionChange(
        webrtc::PeerConnectionInterface::IceConnectionState new_state) {}
    /** Called any time the PeerConnectionState changes */
    virtual void OnConnectionChange(webrtc::PeerConnectionInterface::PeerConnectionState new_state) {}
    /** Called any time the IceGatheringState changes */
    virtual void OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState new_state) = 0;
    /** A new ICE candidate has been gathered */
    virtual void OnIceCandidate(const webrtc::IceCandidateInterface *candidate) = 0;
    /** Gathering of an ICE candidate failed */
    virtual void OnIceCandidateError(const std::string &address,
                            int port,
                            const std::string &url,
                            int error_code,
                            const std::string &error_text) {}
    /** Ice candidates have been removed */
    virtual void OnIceCandidatesRemoved(const std::vector<cricket::Candidate> &candidates) {}
    /** Called when the selected candidate pair for the ICE connection changes. */
    virtual void OnIceSelectedCandidatePairChanged(const cricket::CandidatePairChangeEvent &event) {}
    /** This is called when a receiver and its track are created */
    virtual void OnAddTrack(rtc::scoped_refptr<OHOSRtpReceiverInterface> receiver,
                    const std::vector<rtc::scoped_refptr<OHOSMediaStreamInterface>> &streams) {}
    /** Called when signaling indicates that media will no longer be received on a track */
    virtual void OnRemoveTrack(rtc::scoped_refptr<OHOSRtpReceiverInterface> receiver) {}
    /** This is called when signaling indicates a transceiver will be receiving media from the remote endpoin */
    virtual void OnTrack(rtc::scoped_refptr<OHOSRtpTransceiverInterface> transceiver) {}
  
  protected:
    virtual ~OHOSPeerConnectionObserver() = default;
};

class OHOSPeerConnectionInterface : public webrtc::RefCountInterface {
  public:
    /** Provide a observer to peer connection callbacks */
    virtual void RegisterPeerConnectionObserver(OHOSPeerConnectionObserver *observer) = 0;

    virtual void UnRegisterPeerConnectionObserver() = 0;

    /** Provide a remote candidate to the ICE Agent. */
    virtual void AddIceCandidate(const webrtc::IceCandidateInterface* candidate) = 0;

    virtual void AddIceCandidate(const std::string sdp, int sdp_mline_index, const std::string sdp_mid) = 0;

    /** Remove a group of remote candidates from the ICE Agent. */
    virtual void RemoveIceCandidate(const webrtc::IceCandidateInterface* candidate) = 0;

    /** Sets the PeerConnection's global configuration to `configuration`.
     *  Any changes to STUN/TURN servers or ICE candidate policy will affect the
     *  next gathering phase, and cause the next call to createOffer to generate
     *  new ICE credentials. Note that the BUNDLE and RTCP-multiplexing policies
     *  cannot be changed with this method.
     */
    virtual void SetConfiguration(const webrtc::PeerConnectionInterface::RTCConfiguration& configuration) = 0;

    /** Terminate all media and close the transport. */
    virtual void Close() = 0;

    /** Add a new media stream to be sent on this peer connection.
     *  This method is not supported with RTCSdpSemanticsUnifiedPlan. Please use
     *  addTrack instead.
     */
    virtual bool AddStream(rtc::scoped_refptr<OHOSMediaStreamInterface> stream) = 0;

    /** Remove the given media stream from this peer connection.
     *  This method is not supported with RTCSdpSemanticsUnifiedPlan. Please use
     *  removeTrack instead.
     */
    virtual void RemoveStream(rtc::scoped_refptr<OHOSMediaStreamInterface> stream) = 0;

    /** Add a new media stream track to be sent on this peer connection, and return
     *  the newly created RTCRtpSender. The RTCRtpSender will be
     * associated with the streams specified in the `streamIds` list.
     *
     *  Errors: If an error occurs, returns nil. An error can occur if:
     *  - A sender already exists for the track.
     *  - The peer connection is closed.
     */
    virtual rtc::scoped_refptr<OHOSRtpSenderInterface> AddTrack(
      rtc::scoped_refptr<OHOSMediaTrackInterface> track, const std::vector<std::string> streamIds) = 0;

    /** With PlanB semantics, removes an RTCRtpSender from this peer connection.
     *
     *  With UnifiedPlan semantics, sets sender's track to null and removes the
     *  send component from the associated RTCRtpTransceiver's direction.
     *
     *  Returns YES on success.
     */
    virtual bool  RemoveTrack(rtc::scoped_refptr<OHOSRtpSenderInterface> sender) = 0;

    /** Adds a transceiver with a sender set to transmit the given track. The kind
     *  of the transceiver (and sender/receiver) will be derived from the kind of
     *  the track.
     */
    virtual rtc::scoped_refptr<OHOSRtpTransceiverInterface> AddTransceiver(
      rtc::scoped_refptr<OHOSMediaTrackInterface> track) = 0;

    virtual rtc::scoped_refptr<OHOSRtpTransceiverInterface> AddTransceiver(
      rtc::scoped_refptr<OHOSMediaTrackInterface> track,
      const webrtc::RtpTransceiverInit &init) = 0;

    /** Adds a transceiver with the given kind. Can either be MediaTypeAudio
     *  or MediaTypeVideo.
     */
    virtual rtc::scoped_refptr<OHOSRtpTransceiverInterface> AddTransceiver(
      cricket::MediaType media_type) = 0;

    virtual rtc::scoped_refptr<OHOSRtpTransceiverInterface> AddTransceiver(
      cricket::MediaType media_type, const webrtc::RtpTransceiverInit &init) = 0;

    /** Create a new offer.
     *  The CreateSessionDescriptionSuccess or CreateSessionDescriptionFailure 
     *  callback will be called when done.
     */
    virtual void CreateOffer(rtc::scoped_refptr<OHOSMediaConstraintsInterface> constraints,
                             CreateSessionDescriptionSuccess success,
                             CreateSessionDescriptionFailure failure) = 0;
    /** Create a new offer.
     *  The CreateSessionDescriptionObserver callback will be called when done.
     */
    virtual void CreateOffer(webrtc::CreateSessionDescriptionObserver* observer,
                             rtc::scoped_refptr<OHOSMediaConstraintsInterface> constraints) = 0;  
    /** Create a new answer.
     *  The success or failure callback will be called when done.
     */
    virtual void CreateAnswer(rtc::scoped_refptr<OHOSMediaConstraintsInterface> constraints,
                              CreateSessionDescriptionSuccess success,
                              CreateSessionDescriptionFailure failure) = 0;
    /** Create a new answer.
     *  The CreateSessionDescriptionObserver callback will be called when done.
     */
    virtual void CreateAnswer(webrtc::CreateSessionDescriptionObserver* observer,
                              rtc::scoped_refptr<OHOSMediaConstraintsInterface> constraints) = 0;  
    /** Sets the local session description.
     *  The OnSdpDescriptionCallback callback will be called when done.
     */
    virtual void SetLocalDescription(OnSdpDescriptionCallback callback) = 0;

    virtual void SetLocalDescription(rtc::scoped_refptr<webrtc::SetLocalDescriptionObserverInterface> observer) = 0;

    /** Sets the local session description.
     *  The observer is invoked as soon as the operation completes, which could be
     *  before or after the SetLocalDescription() method has exited
     */
    virtual void SetLocalDescription(std::unique_ptr<webrtc::SessionDescriptionInterface> sdp_desc,
                                     OnSdpDescriptionCallback callback) = 0;

    virtual void SetLocalDescription(std::unique_ptr<webrtc::SessionDescriptionInterface> sdp_desc,
                                     rtc::scoped_refptr<webrtc::SetLocalDescriptionObserverInterface> observer) = 0;
    /** Sets the local session description.
     *  The OnSdpDescriptionCallback callback will be called when done.
     */
    virtual void SetLocalDescription(const std::string sdp_desc,
                                     webrtc::SdpType sdp_type,
                                     OnSdpDescriptionCallback callback) = 0;
  
    /** Sets the local session description.
     *  The observer is invoked as soon as the operation completes
     */
    virtual void SetLocalDescription(const std::string sdp_desc,
                                     webrtc::SdpType sdp_type,
                                     rtc::scoped_refptr<webrtc::SetLocalDescriptionObserverInterface> observer) = 0;
    
    virtual void SetRemoteDescription(std::unique_ptr<webrtc::SessionDescriptionInterface> sdp_desc,
                                      OnSdpDescriptionCallback callback) = 0;
    /** Sets the local session description.
     *  The observer callback will be called when done.
     */
    virtual void SetRemoteDescription(std::unique_ptr<webrtc::SessionDescriptionInterface> sdp_desc,
                                      rtc::scoped_refptr<webrtc::SetRemoteDescriptionObserverInterface> observer) = 0;

    virtual void SetRemoteDescription(const std::string sdp_desc,
                                      webrtc::SdpType sdp_type,
                                      OnSdpDescriptionCallback callback) = 0;
    
    virtual void SetRemoteDescription(const std::string sdp_desc,
                                      webrtc::SdpType sdp_type,
                                      rtc::scoped_refptr<webrtc::SetRemoteDescriptionObserverInterface> observer) = 0;
       
    /** 
     * The spec-compliant GetStats() API. This correspond to the promise-based
     * version of getStats() in JavaScript. Implementation status is described in
     * api/stats/rtcstats_objects.h
     */
    virtual void GetStats(OnStatsCollectorCompletion completion) = 0;
    
    /** 
     * return OHOSRtpSenders
     */
    virtual std::vector<rtc::scoped_refptr<OHOSRtpSenderInterface>> senders() = 0;
    
    /** 
     * return OHOSRtpTransceivers
     */
    virtual std::vector<rtc::scoped_refptr<OHOSRtpTransceiverInterface>> transceivers() = 0;
  
    /** 
     * return OHOSRtpReceivers
     */
    virtual std::vector<rtc::scoped_refptr<OHOSRtpReceiverInterface>> receivers() = 0;
     
    /** 
     * return OHOSMediaStream
     */
    virtual std::vector<rtc::scoped_refptr<OHOSMediaStreamInterface>> local_streams() = 0;

    /** Returns the current SignalingState. */
    virtual webrtc::PeerConnectionInterface::SignalingState signaling_state() = 0;
  
    /** Returns an aggregate state of all ICE *and* DTLS transports.
     *  This is left in place to avoid breaking native clients who expect our old,nonstandard behavior.
     */
    virtual webrtc::PeerConnectionInterface::IceConnectionState ice_connection_state() = 0;

    /** Returns an aggregated state of all ICE transports. */
    virtual webrtc::PeerConnectionInterface::IceConnectionState standardized_ice_connection_state() = 0;

    /** Returns an aggregated state of all ICE and DTLS transports. */
    virtual webrtc::PeerConnectionInterface::PeerConnectionState peer_connection_state() = 0;
    virtual webrtc::PeerConnectionInterface::IceGatheringState ice_gathering_state() = 0;
  
    /** Returns the current state of canTrickleIceCandidates per. */
    virtual absl::optional<bool> can_trickle_ice_candidates() = 0;
  
    /** When a resource is overused, the PeerConnection will try to reduce the load on the sysem. 
     *  for example by reducing the resolution or frame rate of 
     * encoded streams. The Resource API allows injecting platform-specific usage 
     * measurements. The conditions to trigger kOveruse or kUnderuse are up to the
     * implementation
     */
    virtual void AddAdaptationResource(rtc::scoped_refptr<webrtc::Resource> resource) = 0;
};

}

#endif